﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Text;
using System.Threading;

using Sunyi.Project.WebPoint.Common;
using Sunyi.Project.WebPoint.Configuration;
using Sunyi.Project.WebPoint.DataAccessController;
using Sunyi.Project.WebPoint.DataContract;

namespace Sunyi.Project.WebPoint.BusinessLogic
{
    public static class AuditLogger
    {
        static Dictionary<AuditLogOperationCode, Collection<string>> filter = null;
        static AuditLogDaoController controller = new AuditLogDaoController();

        private static Dictionary<AuditLogOperationCode, Collection<string>> Filter
        {
            get
            {
                if (filter == null)
                {
                    filter = new Dictionary<AuditLogOperationCode, Collection<string>>();
                    string[] items = SystemConfiguration.AuditLog[WebPointGlobalConstant.Filter].Split(WebPointGlobalConstant.Comma[0]);

                    foreach (var item in items)
                    {
                        try
                        {
                            AuditLogOperationCode operationCode = (AuditLogOperationCode)Enum.Parse(typeof(AuditLogOperationCode), item.Trim());
                            filter.Add(operationCode, new Collection<string>());
                        }
                        catch
                        {
                            Log log = new Log { Level = LogLevel.Warning.ToString(), Source = typeof(AuditLog).Name };
                            log.UserName = Thread.CurrentThread.Name;
                            log.Data = new ConfigurationErrorsException(item).ToString();
                        }
                    }
                }

                return filter;
            }
        }

        public static AuditLog Select(Guid id)
        {
            return controller.Select(id);
        }

        public static void Write(AuditLog auditLog)
        {
            if (PassFilter(auditLog.OperationCode)) WriterInternal(auditLog);
        }

        public static void Write<T>(AuditLogOperationCode operationCode, string source, T obj)
        {
            if (!PassFilter(operationCode.ToString())) return;

            AuditLog auditLog = new AuditLog();
            auditLog.OperationCode = operationCode.ToString();
            auditLog.Source = source;
            auditLog.Category = string.Empty;
            auditLog.UserName = Thread.CurrentThread.Name;
            auditLog.Data = SerializationHelper.Serialize<T>(obj);

            Write(auditLog);
        }

        public static void Write(AuditLogOperationCode operationCode, string source, params object[] parameters)
        {
            if (!PassFilter(operationCode.ToString())) return;

            StringBuilder sb = new StringBuilder();

            if (parameters != null)
            {
                sb.Append(WebPointGlobalConstant.Parameters);
                sb.Append(WebPointGlobalConstant.Colon);
                sb.Append(WebPointGlobalConstant.Enter);

                foreach (object paramter in parameters) { sb.Append(paramter.ToString()); sb.Append(WebPointGlobalConstant.Comma); sb.Append(WebPointGlobalConstant.Enter); }
            }

            Write(operationCode, source, sb.ToString());
        }

        public static int SearchCount(string operationCode, string source, string category, string userName, DateTime insertTimestamp)
        {
            return controller.SearchCount(operationCode, source, category, userName, insertTimestamp);
        }

        public static Collection<AuditLog> Search(string operationCode, string source, string category, string userName, DateTime insertTimestamp, int pageIndex, int pageSize)
        {
            return controller.Search(operationCode, source, category, userName, insertTimestamp, pageIndex, pageSize);
        }

        public static void DeleteAll()
        {
            controller.DeleteAll();
        }

        #region Private Method

        private static bool PassFilter(string operationCode)
        {
            bool flag = false;

            foreach (AuditLogOperationCode code in Filter.Keys)
            {
                if (code.ToString() == operationCode)
                {
                    flag = true;
                    break;
                }
            }

            return flag;
        }

        private static void WriterInternal(AuditLog auditLog)
        {
            controller.Insert(auditLog);
        }

        #endregion
    }
}
